/* SYSSEG.H
 * Copyright (c) 2007 MissingNODE 
 * Based on GPL OpenQM Code
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 * 
 * 
 * START-HISTORY:
 * Oct-10-2007 Initial Revision
 * END-HISTORY
 *
 * START-DESCRIPTION:
 *
 * END-DESCRIPTION
 *
 * START-CODE
 */
/* File statistic counters. See also BP INT$KEYS.H
   The size of this area is fixed at 24 long ints as it is part of the file
   header. If we ever need to go over this limit, the structure will need to
   be split in the header. Except as indicated, entries are protected by the
   FILE_TABLE_LOCK semaphore.                                                */

struct FILESTATS {
   long int reset;       /*  1: tmtime() value when cleared */
   long int opens;       /*  2: Number of opens */
   long int reads;       /*  3: Number of reads */
   long int writes;      /*  4: Number of writes */
   long int deletes;     /*  5: Number of deletes */
   long int clears;      /*  6: Number of clearfiles */
   long int selects;     /*  7: Number of Basic selects */
   long int splits;      /*  8: Number of splits */
   long int merges;      /*  9: Number of merges */
   long int ak_reads;    /* 10: Number of AK reads */
   long int ak_writes;   /* 11: Number of AK writes */
   long int ak_deletes;  /* 12: Number of AK deletes */
   long int spare[12];
};
#define FILESTATS_COUNTERS 12    /* Used counters */


/* System shared segment. */

typedef volatile struct SYSSEG SYSSEG;
struct SYSSEG {
   unsigned long int revstamp;   /* TM revstamp that create the memory */
   long int shmem_size;          /* Shared memory size */
   short int task_locks[64];     /* User number of lock owner. Zero if free.
                                    Protected by SHORT_CODE semaphore. */
   short int num_files;          /* Number of file table entries */
   short int used_files;         /* Number of used cells including embedded
                                    free cells. Protected by FILE_TABLE_LOCK */
   short int num_rlocks;         /* Number of record lock table entries */
   short int num_glocks;         /* Number of group lock table entries */
   short int max_users;          /* User limit (all processes) */
   short int last_user;          /* Last user number allocated (cyclic) */
   short int hi_user_no;         /* Highest valid user number... */
     #define MIN_HI_USER_NO 1023 /* ...and its minimum value */
   int tmlnxd_pid;               /* PID of tmlnxd daemon */
   char sysdir[MAX_PATHNAME_LEN+1];
   bool deadlock;                /* DEADLOCK: Trap deadlocks? */
   int errlog;                   /* ERRLOG: Max size of errlog in bytes */
   short int fds_limit;
   long int fds_rotate;
   short int fixusers_base;      /* FIXUSERS: First user number and... */
   short int fixusers_range;     /*          ...Number of ports/users */
   short int max_id_len;         /* MAXIDLEN: Max record id length */
   short int netfiles;           /* NETFILES: 0x0001   Allow outgoing NFS
                                              0x0002   Allow incoming TMNet */
   short int portmap_base_port;  /* PORTMAP: First port number ... */
   short int portmap_base_user;  /*          ...First user number... */
   short int portmap_range;      /*          ...Number of ports/users */
   unsigned long int flags;
     #define SSF_SECURE     0x00000001   /* Secure mode? */
     #define SSF_SUSPEND    0x00000020   /* Suspend writes */
// MS 16 bits from from DEBUG configuration parameter
     #define SSF_PRTDEBUG   0x00010000   /* Debug printer actions */
     #define SSF_TMFIX      0x00020000   /* Allow TMFix in interactive mode */
     #define SSF_MONITOR    0x00040000   /* Run in monitor mode */
     #define SSF_INT_PDUMP  0x00080000   /* Allow PDUMP to dump internal mode */

   struct FILESTATS global_stats; /* Global file stats (see DH.H) */
   unsigned long next_txn_id;    /* Next transaction id */
   long int prtjob;              /* Print job number (SHORT_CODE semaphore) */

   short int jnlmode;            /* JNLMODE: Journal mode */
   int jnlseq;                   /* Journal file sequence no. 0 = inactive.
                                    Protected by JNL_SEM */
   char jnldir[MAX_PATHNAME_LEN+1]; /* JNLDIR: Journal file directory */
   char startup[80+1];           /* STARTUP: Startup command */

   /* Group lock counters (Protected by GROUP_LOCK_SEM) */
   unsigned long int gl_count;   /* Number of group locks obtained */
   unsigned long int gl_wait;    /* Group locks blocked on first attempt */
   unsigned long int gl_retry;   /* Group locks blocked on subsequent attempt */
   unsigned long int gl_scan;    /* Number of steps to obtain group lock */
   long int file_table;          /* Offset of file table */
   long int rlock_table;         /* Offset of record lock table... */
   short int rlock_entry_size;   /* ...and size of each entry */
   long int glock_table;         /* Offset of group lock table */
   long int semaphore_table;     /* Offset of semaphore owner table */
   long int user_table;          /* Offset of user table */
   short int user_entry_size;    /* Size of user table entry */
   long int user_map;            /* Offset of user map */
   long int pcode_offset;        /* Pcode */
   long int pcfg_offset;         /* Offset to template pcfg structure */
   int pcode_len;
};

public SYSSEG * sysseg init(NULL);   /* 0234 */

/* Semaphores
   Aquisition sequence must always be decreasing semaphore number
   First: JNL_SEM          Single threads journal file updates
          FILE_TABLE_LOCK  Protects updates to file table.
          REC_LOCK_SEM     Protects updates to lock table and to lock_state in
                           file table entry.
          GROUP_LOCK_SEM   Protects group lock table.
   Last:  SHORT_CODE       Protects short in-line code sequences.
*/

/* ======================================================================
   Semaphore Table                                                        */

typedef struct SEMAPHORE_ENTRY SEMAPHORE_ENTRY;
struct SEMAPHORE_ENTRY
 {
  short int owner;         /* TM user number of owner, zero if free */
  short int where;         /* Where was this last taken? (See MEM_TAGS) */
 };

#define SHORT_CODE       0
#define ERRLOG_SEM       1
#define GROUP_LOCK_SEM   2
#define REC_LOCK_SEM     3
#define FILE_TABLE_LOCK  4
#define JNL_SEM          5
#define NUM_SEMAPHORES   6
public char sem_tags[] init("SHCLOGGLTRLTFLTJNL"); /* 3 chars per semaphore */

   public int semid;

/* ======================================================================
   User Table                                                             */

typedef volatile struct USER_ENTRY USER_ENTRY;
struct USER_ENTRY
 {
  long int pid;                    /* OS process id */
  short int uid;                   /* Internal user id. Zero if spare cell.
                                      -1 = reserved for new phantom */
  short int puid;                  /* Parent user id. Zero if not phantom */
  char username[MAX_USERNAME_LEN+1];  /* Login user name */
  char ip_addr[15+1];
  #define MAX_TTYNAME_LEN 15
  char ttyname[MAX_TTYNAME_LEN+1];
  short int flags;                 /* Also defined in INT$KEYS.H */
     #define USR_PHANTOM     0x0001 /* Is a phantom */
     #define USR_LOGOUT      0x0002 /* Logout in progress */
     #define USR_TMVBSRVR    0x0004 /* Is TMVbSrvr process */
     #define USR_ADMIN       0x0008 /* Administrator privileges */
     #define USR_TMNET       0x0010 /* Is TMNet (USR_TMVBSRVR also set) */
     #define USR_CHGPHANT    0x0020 /* "Chargeable" phantom; counts as licensed user */
     #define USR_MSG_OFF     0x0040 /* Message reception disabled */
     #define USR_WAKE        0x0080 /* Set by op_wake, cleared by op_pause */
  unsigned short int events;        /* Any bit set causes processing interrupt */
     #define EVT_LOGOUT      0x0001 /* Forced logout - immediate termination */
     #define EVT_STATUS      0x0002 /* Return status dump */
     #define EVT_UNLOAD      0x0004 /* Unload inactive cached object code */
     #define EVT_BREAK       0x0008 /* Set break inhibit to zero */
     #define EVT_HSM_ON      0x0010 /* Start HSM */
     #define EVT_HSM_DUMP    0x0020 /* Return HSM data */
     #define EVT_PDUMP       0x0040 /* Force process dump */
     #define EVT_FLUSH_CACHE 0x0080 /* Flush DH cache */
     #define EVT_JNL_SWITCH  0x0100 /* Switch journal file */
     #define EVT_TERMINATE   0x0200 /* Forced logout - graceful termination */
     #define EVT_MESSAGE     0x0400 /* Send immediate message */
     #define EVT_LICENCE     0x0800 /* Logout from licence expiry */

  /* Lock wait data (protected by REC_LOCK_SEM) */

   short int lockwait_index;       /* 0 = not waiting,
                                      +ve = rec lock table index (record lock),
                                      -ve = file table index (file lock) */
   unsigned short int file_map[1];          /* Count of opens by file.
                                               Protected by FILE_TABLE_LOCK */
 };

/* UMap(n)    Returns pointer to user map entry for user n */
#define UMap(n) (((short int *)(((char *)sysseg) + sysseg->user_map)) + (n))

/* UserPtr(n) Returns pointer for table entry for user n */
#define UserPtr(n) ((*(UMap(n))!=0)?UPtr(*(UMap(n))):NULL)

/* UPtr(n)    Returns pointer for table index n, not user n (from 1) */
#define UPtr(n) ((USER_ENTRY *)(((char *)sysseg) + sysseg->user_table + (((n) - 1) * sysseg->user_entry_size)))

/* UFMPtr(uptr,fno)  Pointer to user/file map table entry. Fno from 1 */
#define UFMPtr(uptr,fno) ((unsigned short int *)&((uptr)->file_map[(fno)-1]))

public USER_ENTRY * my_uptr init(NULL);

